<?php

/**
 * Description of x10_Config
 *
 * @author prometheus
 */
class x10_Config
{
	/**
	 * Az osztály birtokosa
	 * @var x10_GeneralClass
	 */
	public $owner;
	protected $settings;
	protected $overrides;

	/**
	 * Konstruktor.
	 * Eltárolja a szolgáltató beállításait a {@link setConfig} metódus
	 * hívásával.
	 * @param Array|Object|String $config A beállító elem vagy annak JSON formátumú
	 * elérési útja (URL formában)
	 * @param Array|Object $overrides A feldolgozott beállítások
	 * alapértelmezéseit lehet felülbírálni azonos kulcsok megadásával
	 * @param Bool $asArray Ha TRUE, JSON beolvasásnál tömb lesz minden objektum
	 * @throws E_Provider_ConfigNotExists
	 * @throws E_Provider_ConfigParseError
	 */
	public function __construct($config, $overrides=NULL, $asArray=FALSE)
	{
		$this->overrides = $overrides;
		$this->setConfig($config, $asArray);
	}

	/**
	 * Módosítja a beállításokat.
	 * @param Array|Object|String $config
	 * @return Provider
	 * @throws E_Provider_ConfigNotExists
	 * @throws E_Provider_ConfigParseError
	 */
	public function setConfig($config, $asArray=FALSE)
	{
		$error = FALSE;
		$found = FALSE;
		
		if (is_object($config) and $config instanceof x10_Util_JSON)
		{
			$cfg = $config->get();
			unset($config);
			$config = $cfg;
		}
		else if (is_object($config) and $config instanceof x10_ConfigWrapper)
		{
			$config = $config->settings;
		}
		else if ((is_object($config)) or (is_string($config) and strpos($config, 'cfg://') !== FALSE))
		{
			if (is_string($config) and strpos($config, 'cfg://') !== FALSE)
			{
				$config = str_replace('.', '_', substr($config, 6));
			}
			$cfgPath = x10::$configRoot.x10::getConfigFileNameFor($config);
			$cfgJSON = NULL;
			if (file_exists($cfgPath))
			{
				$cfgJSON = new x10_Util_JSON(
					'file://'.$cfgPath,
					$asArray
				);
				$config = $cfgJSON->get();
			}
			else
			{
				$config = array();
			}
			unset($cfgJSON);
		}
		else if (is_array($config))
		{
			// ok.
		}
		else
		{
			try
			{
				// Az utolsó remény, hogy valami értelmezhetőt nyerjünk ki a paraméterből
				$config = (string)$config;
			}
			catch (x10_E_Config_ParseError $e)
			{
				$config = '&lt;nem meghatározható&gt;';
			}
			throw new x10_E_Config_ParseError($config, '&lt;nem meghatározható&gt;', 'a konstruktornak adott paraméter hibás');
		}

		$this->settings = $config;
		if (!is_null($this->overrides)) $this->settings = $this->setOverridesRecursive($this->settings, $this->overrides);

		return $this;
	}
	
	public function hasSettings()
	{
		return (is_array($this->settings)? (bool)count($this->settings) : !is_null($this->settings));
	}
	
	public function override($overrides)
	{
		if (!is_null($overrides)) $this->settings = $this->setOverridesRecursive($this->settings, $overrides);
	}
	
	protected function setOverridesRecursive($mapTo, $overrides)
	{
		if (is_object($overrides) and $overrides instanceof x10_Config)
		{
			$overrides = $overrides->getConfig();
		}

		if (is_array($overrides))
		{
			if (count($overrides) == 0) return array();
			foreach ($overrides as $sKey2 => $sValue2)
			{
				if (is_object($mapTo)) $mapTo->$sKey2 = $this->setOverridesRecursive(&$mapTo->$sKey2, $sValue2);
				else if (is_array($mapTo)) $mapTo[$sKey2] = $this->setOverridesRecursive(&$mapTo[$sKey2], $sValue2);
			}
		}
		elseif (is_object($overrides))
		{
			if (count((array)$overrides) == 0) return new stdClass();
			foreach ($overrides as $sKey2 => $sValue2)
			{
				if (is_object($mapTo)) $mapTo->$sKey2 = $this->setOverridesRecursive(&$mapTo->$sKey2, $sValue2);
				else if (is_array($mapTo)) $mapTo[$sKey2] = $this->setOverridesRecursive(&$mapTo[$sKey2], $sValue2);
			}
		}
		else
		{
			return $overrides;
		}
		
		return $mapTo;
	}
	
	/**
	 * Visszatér a beállításokkal.
	 * @return Array
	 */
	public function getConfig()
	{
		return $this->settings;
	}

	/**
	 * Beállítja a konfiguráció megadott kulcsához tartozó értéket.
	 *
	 * @param String $key
	 * @param Mixed $value
	 * @return Provider
	 */
	public function setConfigKey($key, $value)
	{
		if (is_array($this->settings)) $this->settings[$key] = $value;
		else if (is_object($this->settings)) $this->settings->$key = $value;
		return $this;
	}

	/**
	 * Visszaadja a megadott kulcshoz tartozó beállítási értéket.
	 *
	 * @param String $key
	 * @return Mixed
	 */
	public function getConfigKey($key)
	{
		if (is_array($this->settings)) return (isset($this->settings[$key])? $this->settings[$key] : NULL);
		else if (is_object($this->settings)) return (isset($this->settings->$key)? $this->settings->$key : NULL);
	}
}

?>